package jp.ac.u_tokyo.dch.action.data;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import jp.ac.u_tokyo.dch.core.db.DBConnection;
import jp.ac.u_tokyo.dch.core.exceptions.DBException;
import jp.ac.u_tokyo.dch.model.db.Data;
import jp.ac.u_tokyo.dch.model.db.DataDetail;
import jp.ac.u_tokyo.dch.model.db.DataFile;
import jp.ac.u_tokyo.dch.model.db.DataSchema;
import jp.ac.u_tokyo.dch.model.db.DataSchemaDetail;
import jp.ac.u_tokyo.dch.model.xml.DisplayDefine;
import jp.ac.u_tokyo.dch.service.DaoServiceAware;
import jp.ac.u_tokyo.dch.service.DataSchemaService;
import jp.ac.u_tokyo.dch.service.DataService;
import jp.ac.u_tokyo.dch.service.Transaction;
import jp.ac.u_tokyo.dch.util.DchCommonUtil;
import jp.ac.u_tokyo.dch.util.common.ModoruUtil;
import jp.ac.u_tokyo.dch.util.common.CommonUtil;
import jp.ac.u_tokyo.dch.util.common.DisplayUtil;
import jp.ac.u_tokyo.dch.view.Constants;
import jp.ac.u_tokyo.dch.view.outputdata.DataView;

import org.apache.commons.lang.xwork.StringUtils;
import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

/**
 *
 * データ登録、編集、削除処理を担当
 * @version 1.1
 *
 */
public class DataAction extends ActionSupport implements ModelDriven<DataView>, DaoServiceAware {

	/**
	 *シリアル番号
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * DBコネクションオブジェクト
	 */
	private DBConnection dbConnection = null;

	/**
	 * 画面モデル
	 */
	private DataView view = new DataView();

	/**
	 * スキーマリスト
	 */
	private List<DataSchema> dataSchemaList;

	/**
	 * メータスキーマ定義
	 */
	private DisplayDefine define;

	/**
	 * タイプ
	 */
	private String actionType;

	/**
	 * データスキーマサービス
	 */
	private DataSchemaService service = null;
	/**
	 * データサービス
	 */
	private DataService dataService = null;

	/**
	 * 初期化処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String init() throws Exception {

		return SUCCESS;
	}

	/**
	 * スキーマ選択
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String selectschema() throws Exception {

		ModoruUtil.modoruProcess(ServletActionContext.getRequest(), "/outputdata/selectschema", ServletActionContext.getRequest().getQueryString());

		service = new DataSchemaService(dbConnection);

		String sort =  view.getSort();

		dataSchemaList = service.getList(sort);

		return SUCCESS;

	}
	/**
	 * 登録処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String add() throws Exception {

		actionType = Constants.ADD;

		HttpServletRequest request = ServletActionContext.getRequest();
		String schemaid = request.getParameter("schemaid");
		String sort = request.getParameter("sort");

		view.setSort(sort);

		initSchema(sort, schemaid);

		String fUserId = DchCommonUtil.getLoginIdFromRequest(ServletActionContext.getRequest());
		view.getData().setSchemaId(schemaid);
		view.getData().setSort(view.getSort());
		view.getData().setCreateUser(fUserId);
		view.getData().setCreateDate(DchCommonUtil.getCurrentDate());
		view.getData().setModifyUser(fUserId);
		view.getData().setModifyDate(DchCommonUtil.getCurrentDate());


		return SUCCESS;
	}
	/**
	 * 親選択処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String oyaselect() throws Exception {

		view.getData().setOyaId(view.getOyaId());
		view.getData().setOyaName(view.getOyaName());

		initSchema(view.getSort(), view.getData().getSchemaId());

		return SUCCESS;
	}
	/**
	 * ファイル追加処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String addFileInfo() throws Exception {

		DataFile dataFile = view.getAddFileInfo();

		view.getDataFileList().add(dataFile);

		initSchema(view.getSort(), view.getData().getSchemaId());

		return SUCCESS;
	}
	/**
	 * ファイル削除処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String deleteFileInfo() throws Exception {

		List<DataFile> dataFileList = view.getDataFileList();
		String deleteMutiMediaIndex = view.getDeleteMutiMediaIndex();
		int removeIndex = Integer.valueOf(deleteMutiMediaIndex);
		dataFileList.remove(removeIndex);

		initSchema(view.getSort(), view.getData().getSchemaId());

		return SUCCESS;
	}

	/**
	 * 編集処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String editInit() throws Exception {

		actionType = Constants.MOD;

		dataService = new DataService(dbConnection);

		HttpServletRequest request = ServletActionContext.getRequest();
		String dataid = request.getParameter("dataid");
		String schemaid = request.getParameter("schemaid");
		String datasort = request.getParameter("datasort");

		initSchema(datasort, schemaid);

		view.setSort(datasort);

		dataService.dbDataToView(dataid, view);

		String fUserId = DchCommonUtil.getLoginIdFromRequest(ServletActionContext.getRequest());
		view.getData().setModifyUser(fUserId);
		view.getData().setModifyDate(DchCommonUtil.getCurrentDate());


		return SUCCESS;
	}

	/**
	 * コピー処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String copyInit() throws Exception {

		actionType = Constants.ADD;

		dataService = new DataService(dbConnection);

		HttpServletRequest request = ServletActionContext.getRequest();
		String dataid = request.getParameter("dataid");
		String schemaid = request.getParameter("schemaid");
		String datasort = request.getParameter("datasort");

		initSchema(datasort, schemaid);

		view.setSort(datasort);

		dataService.dbDataToView(dataid, view);

		String fUserId = DchCommonUtil.getLoginIdFromRequest(ServletActionContext.getRequest());
		view.getData().setId("");
		view.getData().setCreateUser(fUserId);
		view.getData().setCreateDate(DchCommonUtil.getCurrentDate());
		view.getData().setModifyUser(fUserId);
		view.getData().setModifyDate(DchCommonUtil.getCurrentDate());


		return SUCCESS;
	}
	/**
	 * 削除処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String delInit() throws Exception {

		actionType = Constants.DEL;

		dataService = new DataService(dbConnection);

		HttpServletRequest request = ServletActionContext.getRequest();
		String dataid = request.getParameter("dataid");
		String schemaid = request.getParameter("schemaid");
		String datasort = request.getParameter("datasort");

		initSchema(datasort, schemaid);

		view.setSort(datasort);

		dataService.dbDataToView(dataid, view);

		String fUserId = DchCommonUtil.getLoginIdFromRequest(ServletActionContext.getRequest());
		view.getData().setModifyUser(fUserId);
		view.getData().setModifyDate(DchCommonUtil.getCurrentDate());

		define = DisplayUtil.getItemDefine(view.getSort());

		return SUCCESS;
	}

	/**
	 * 確認画面から戻る処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String modoru() throws Exception {

		initSchema(view.getSort(), view.getData().getSchemaId());

		return SUCCESS;
	}
	/**
	 * 確認処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	public String confirm() throws Exception {

		initSchema(view.getSort(), view.getData().getSchemaId());

		dataService = new DataService(dbConnection);

		Data data = view.getData();
		String sort = view.getSort();
		String name = data.getName();
		String id = data.getId();

		List<DataDetail> list = view.getDataDetailList();
		List<DataDetail> customDatalist = view.getCustomDataDetailList();
		List<DataFile> fileList = view.getDataFileList();

		if (StringUtils.isEmpty(name)) {
			addFieldError("data.name", getText("requiredstring", new String[] { "データ名称" }));
			return ERROR;
		}

		if (StringUtils.contains(name, "\"")) {
			addFieldError("data.name", getText("escapeerror", new String[] { "データ名称" }));
			return ERROR;
		}

		if (CommonUtil.oyaEmpty(sort, data.getOyaId())) {
			addFieldError("id", getText("requiredstring", new String[] { "親データ" }));
			return ERROR;
		}

		if (Constants.LV7_SORT.equals(sort) && fileList.size() == 0) {
			addFieldError("id", getText("requiredstring", new String[] { "画像・動画情報" }));
			return ERROR;
		}

		if (dataService.checkName(sort, name, id)) {
			addFieldError("data.name", getText("duplicateMsg"));
			return ERROR;

		}
		hissuCheck(list);
		hissuCheck(customDatalist);

		if (hasErrors()) {
			return ERROR;
		}

		return SUCCESS;
	}

	/**
	 * 登録、削除、編集処理
	 * @return 結果
	 * @throws Exception 例外
	 */
	@Transaction
	public String execute() throws Exception {

		dataService = new DataService(dbConnection);

		initSchema(view.getSort(), view.getData().getSchemaId());

		if (Constants.ADD.equals(actionType)) {

			dataService.insert(view);

		} else if (Constants.MOD.equals(actionType)) {

			dataService.update(view);

		} else if (Constants.DEL.equals(actionType)) {

			dataService.delete(view);
		}

		return SUCCESS;
	}

	/**
	 *
	 * @return スキーマリスト
	 */
	public List<DataSchema> getDataSchemaList() {
		return dataSchemaList;
	}

	/**
	 *
	 * @return 画面名を返す
	 */
	public String getGamenName() {
		return getText("outputmenu_" + view.getSort());
	}
	/**
	 *
	 * @return 親画面名を返す
	 */
	public String getGamenOyaName() {

		return getText("outputmenu_" + view.getOyaSort());
	}
	/**
	 * 順番によって項目キーを生成
	 * @param 順番
	 * @return 項目キー
	 */
	public String getFieldKey(String index) {
		return CommonUtil.getFieldKey(view.getSort(), index);
	}
	/**
	 *
	 * @param fieldkey 項目キー
	 * @return スキーマ詳細情報
	 */
	public DataSchemaDetail getDataSchemaDetailByFieldKey(String fieldkey) {
		return view.getDataSchemaDetailMap().get(fieldkey);
	}

	/**
	 *
	 * @param fieldkey 項目キー
	 * @return スキーマ詳細情報
	 */
	public DataDetail getDataDetailByFieldKey(String fieldkey) {
		return view.getDataDetailMap().get(fieldkey);
	}

	/**
	 * データ項目リスト
	 * @param fieldkey 項目キー
	 * @return データ項目マップ
	 */
	public Map<String, String> makeOptionList(String fieldkey) {

		DataSchemaDetail detail = view.getDataSchemaDetailMap().get(fieldkey);

		String options = detail.getOptions();
		String inputType = detail.getInputType();
		String optionKbn = detail.getOptionKbn();

		Map<String, String> map = new LinkedHashMap<String, String>();

		int i = 0;

		for (String option : options.split(Constants.OPTION_DEL)) {
			map.put(String.valueOf(i), option);
			i++;
		}

		if ("3".equals(inputType) || "4".equals(inputType)) {

			if ("1".equals(optionKbn)) {
				map.put(Constants.FREE_IDENTITY, "その他");
			}
		}
		return map;

	}

	/**
	 * データが複数の場合コンマに分けて返す
	 * @param fieldkey 項目キー
	 * @param keys オプションキー
	 * @param otherData その他データ
	 * @return データ表示
	 */
	public String convertName(String fieldkey, String[] keys, String otherData) {

		StringBuilder convertName = new StringBuilder();

		DataSchemaDetail detail = view.getDataSchemaDetailMap().get(fieldkey);

		String options = detail.getOptions();


		for (String key : keys) {

			int i = 0;

			for (String option : options.split(Constants.OPTION_DEL)) {

				if (String.valueOf(i).equals(key)) {
					convertName.append(option);
					convertName.append(",");
					break;
				}
				i++;
			}

			if (StringUtils.contains(key, Constants.FREE_IDENTITY)) {

				convertName.append(otherData);
				convertName.append(",");
			}
		}

		if (convertName.length() != 0) {
			convertName.deleteCharAt(convertName.length() - 1);
		}

		return convertName.toString();
	}

	public String convertMultiText(String texts) {

		StringBuilder convertName = new StringBuilder();

		for (String text : texts.split("\n")) {

			convertName.append(text);
			convertName.append(",");
		}

		if (convertName.length() != 0) {

			convertName.deleteCharAt(convertName.length() - 1);
		}

		return convertName.toString();
	}

	/**
	 *
	 * @return メータスキーマ定義
	 */
	public DisplayDefine getDefine() {
		return define;
	}
	/**
	 *
	 * @param define メータスキーマ定義
	 */
	public void setDefine(DisplayDefine define) {
		this.define = define;
	}
	/**
	 *
	 * @return 実行タイプ
	 */
	public String getActionType() {
		return actionType;
	}
	/**
	 *
	 * @param 実行タイプ
	 */
	public void setActionType(String actionType) {
		this.actionType = actionType;
	}
	/**
	 * DBコネクションオブジェクトをセットする
	 */
	@Override
	public void setDBConnection(DBConnection con) {
		dbConnection = con;
	}
	/**
	 * 画面モデルを返す
	 */
	@Override
	public DataView getModel() {
		return view;
	}

	private void initSchema(String sort, String schemaid) throws DBException {

		service = new DataSchemaService(dbConnection);
		define = DisplayUtil.getItemDefine(sort);
		view.setSchemaItemList(service.getSchemaDetailList(schemaid, "0"));
		view.setCustomItemList(service.getSchemaDetailList(schemaid, "1"));
	}

	/**
	 *必須チェックを行う
	 * @param list データリスト
	 */
	private void hissuCheck(List<DataDetail> list) {

		if (list != null) {

			for (DataDetail detail : list) {

				String fieldKey = detail.getFieldKey();
				String dataContent[] = detail.getData();

				DataSchemaDetail schemaDetail = getDataSchemaDetailByFieldKey(fieldKey);
				String hissuSign = schemaDetail.getHissuSelectSign();
				String inputType = schemaDetail.getInputType();
				String itemName = schemaDetail.getFieldItemName();

				if (Constants.HISSU_SIGN_HISSU.equals(hissuSign)
						&& !Constants.INPUT_TYPE_FIELDSELECT.equals(inputType)) {

					if (dataContent == null || dataContent.length == 0) {
						addFieldError("id", getText("requiredstring", new String[] {"必須項目:" +  itemName }));
					} else if (dataContent.length == 1 && dataContent[0].length() == 0) {
						addFieldError("id", getText("requiredstring", new String[] {"必須項目:" +  itemName }));
					}
				}

			}
		}

	}
}
